#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__

#include <iostream>
#include "../mqcommon/mq_logger.hpp"
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_msg.pb.h"

namespace mymq
{
    class Router
    {
        public:
            static bool isLegalRoutingKey(const std::string& routing_key)
            {
                //  routing_key:判断是否含有非法字符即可，合法字符：a~z,A~Z,0~9,.,_
                for(auto& ch:routing_key)
                {
                    if( (ch >= 'a' && ch <= 'z') ||
                        (ch >= 'A' && ch <= 'Z') ||
                        (ch >= '0' && ch <= '9') ||
                        (ch == '_' || ch == '.'))
                    {
                        continue;
                    }
                    return false;
                }
                return true;
            }

            static bool isLegalBindingKey(const std::string& binding_key)
            {
                //  1.判断是否含有非法字符即可，合法字符：a~z,A~Z,0~9,.,_,*,#
                for(auto& ch:binding_key)
                {
                    if( (ch >= 'a' && ch <= 'z') ||
                        (ch >= 'A' && ch <= 'Z') ||
                        (ch >= '0' && ch <= '9') ||
                        (ch == '_' || ch == '.') ||
                        (ch == '*' || ch == '#'))
                    {
                        continue;
                    }
                    return false;
                }
                
                // 2.* 和 #必须独立存在
                std::vector<std::string> sub_words;
                StrHelper::split(binding_key,".",sub_words);
                for(auto& word : sub_words)
                {
                    if (word.size() > 1 && 
                       (word.find("*") != std::string::npos || 
                        word.find("#") != std::string::npos))
                    {
                        return false;
                    }
                }
                // 3.* 和 #不能连续出现(#两边不允许有任意*,但*可以是连续的)
                // *是任意一个单词，而#是零个或多个任意单词
                for(int i = 1;i<sub_words.size();i++)
                {
                    if (sub_words[i] == "#" && sub_words[i - 1] == "*")
                    {
                        return false;
                    }
                    if (sub_words[i] == "#" && sub_words[i - 1] == "#")
                    {
                        return false;
                    }
                    if (sub_words[i] == "*" && sub_words[i - 1] == "#")
                    {
                        return false;
                    }
                }
                return true;
            }

            static bool route(ExchangeType type,const std::string& routing_key,const std::string& binding_key)
            {
                if(type == ExchangeType::DIRECT)
                {
                    return (routing_key == binding_key);
                }
                else if(type == ExchangeType::FANOUT)
                {
                    return true;
                }
                else
                {
                    // 主题交换：要进行模式匹配（动态规划）
                    // 1.将binding_key和routing_key进行字符串分割，得到各个单词数组
                    std::vector<std::string> bkeys,rkeys;
                    int n_bkey = StrHelper::split(binding_key,".",bkeys);
                    int n_rkey = StrHelper::split(routing_key,".",rkeys);
                    // 2.定义标记数组，并初始化[0][0]位置为true，其他位置为false
                    std::vector<std::vector<bool>> dp(n_bkey+1,std::vector<bool>(n_rkey+1,false));
                    dp[0][0] = true;
                    // 3.若binding_key以#起始，那么#对应行的第0列为true
                    for(int i = 1; i <= bkeys.size(); i++) 
                    {
                        if (bkeys[i - 1] == "#") 
                        {
                            dp[i][0] = true;
                            continue;
                        }
                        break;
                    }
                    // 4.使用routing_key和binding_key每个单词进行匹配并标记数组
                    for(int i = 1;i<=n_bkey;i++)
                    {
                        for(int j = 1;j<=n_rkey;j++)
                        {
                            //如果当前bkey是个*，或者两个单词相同，表示单词匹配成功，则从左上方继承结果
                            if(bkeys[i-1] == rkeys[j-1] || bkeys[i-1] == "*")
                            {
                                dp[i][j] = dp[i-1][j-1];
                            }
                            else if(bkeys[i-1] == "#")
                            {
                                //如果当前bkey是个#，则需要从左上，左边，上边继承结果
                                dp[i][j] = dp[i-1][j-1] | dp[i][j-1] | dp[i-1][j];
                            }
                        }
                    }
                    return dp[n_bkey][n_rkey];
                }

            }
                
    };
}




#endif